package com.example.demo.view

import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.toUpperCase
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import kotlinx.coroutines.delay
import java.util.*
import kotlin.random.Random


@Composable
fun HelloContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        /**
         * Remember the value produced by init.
         * It behaves similarly to remember, but the stored value will survive the activity
         * or process recreation using the saved instance state mechanism (for example it happens
         * when the screen is rotated in the Android application).
         */
        var name by rememberSaveable { mutableStateOf("") }
        if (name.isNotEmpty()) {
            Text(
                text = "Hello, $name!",
                modifier = Modifier.padding(bottom = 8.dp),
                style = MaterialTheme.typography.h5
            )
        }
        OutlinedTextField(
            value = name,
            onValueChange = { name = it },
            label = { Text("Name") }
        )
    }
}

//https://developer.android.google.cn/jetpack/compose/state#state-hoisting
@Composable
fun HelloContent(name :String, onNameChanged: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {

        if (name.isNotEmpty()) {
            Text(
                text = "Hello, $name!",
                modifier = Modifier.padding(bottom = 8.dp),
                style = MaterialTheme.typography.h5
            )
        }
        OutlinedTextField(
            value = name,
            onValueChange = { onNameChanged(it) },
            label = { Text("Name") }
        )
    }
}

//@Composable
//fun HelloScreen() {
//    var name by rememberSaveable { mutableStateOf("") }
//
//    HelloContent(name = name, onNameChanged = { name = it })
//}

val SplashWaitTimeMillis = 3000L

@Composable
fun LandingScreen(stage:State<Int>, onTimeout: () -> Unit) {

    Log.i("LandingScreen"," ****Composition or Re-composition,stage=${stage.value}")

    // This will always refer to the latest onTimeout function that
    // LandingScreen was recomposed with
    val currentOnTimeout by rememberUpdatedState(onTimeout)

    // Create an effect that matches the lifecycle of LandingScreen.
    // If LandingScreen recomposes, the delay shouldn't start again.
    LaunchedEffect(true) {
        delay(SplashWaitTimeMillis)
        currentOnTimeout()
//        onTimeout()
    }

    /* Landing screen content */
    if(stage.value == 0) {
        Text("Landing.....stage=${stage.value}")
    }

    Text("stage=${stage.value}")
}

@Composable
fun TranslationScreen(content: String, onChanged:(String)->Unit){


    Column {

        Text(text = "${content}")

        TextField(value = content, onValueChange = { onChanged(it)} )
    }
}

//https://developer.android.google.cn/jetpack/compose/side-effects#disposableeffect
@Composable
fun HelloContent(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onCreate: () -> Unit,
    onStart: () -> Unit,
    onResume: () -> Unit,
    onPause: () -> Unit,
    onStop: () -> Unit,
    onDestroy: () -> Unit) {

    /**
     * rememberUpdatedState should be used when parameters or values computed during composition
     * are referenced by a long-lived lambda or object expression.
     * Recomposition will update the resulting State without recreating the long-lived lambda or object,
     * allowing that object to persist without cancelling and resubscribing,
     * or relaunching a long-lived operation that may be expensive or prohibitive to recreate and restart.
     */
    val currentOnStart by rememberUpdatedState(newValue = onStart)
    val currentOnStop by rememberUpdatedState(newValue = onStop)
    val currentOnDestroy by rememberUpdatedState(newValue = onDestroy)
    val currentOnCreate by rememberUpdatedState(newValue = onCreate)
    val currentOnPause by rememberUpdatedState(newValue = onPause)
    val currentOnResume by rememberUpdatedState(newValue = onResume)

    /**
     * A side effect of composition that must run for any new unique value of key1
     * and must be reversed or cleaned up if key1 changes or if the DisposableEffect leaves the composition.
     *
     * A DisposableEffect's key is a value that defines the identity of the DisposableEffect.
     * If a key changes, the DisposableEffect must dispose its current effect and reset by calling effect again.
     * Examples of keys include:
     * Observable objects that the effect subscribes to
     * Unique request parameters to an operation that must cancel and retry if those parameters change
     *
     * DisposableEffect may be used to initialize or subscribe to a key and reinitialize
     * when a different key is provided, performing cleanup for the old operation before initializing the new.
     */
    DisposableEffect(lifecycleOwner){

        val observer = LifecycleEventObserver { _, event ->
            when(event){
                Lifecycle.Event.ON_CREATE -> currentOnCreate()
                Lifecycle.Event.ON_START -> currentOnStart()
                Lifecycle.Event.ON_RESUME -> currentOnResume()
                Lifecycle.Event.ON_PAUSE -> currentOnPause()
                Lifecycle.Event.ON_STOP -> currentOnStop()
                Lifecycle.Event.ON_DESTROY -> currentOnDestroy()
            }
        }

        lifecycleOwner.lifecycle.addObserver(observer)

        /**
         * Provide onDisposeEffect to the DisposableEffect to run when it leaves the composition or its key changes.
         */
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

@Composable
fun HelloScreen() {

    val number = Random.nextInt()

    HelloContent(
        onStart = { Log.i("HelloScreen","onStart*****$number")},
        onStop = { Log.i("HelloScreen","onStop****$number")},
        onDestroy = { Log.i("HelloScreen","onDestroy****$number")},
        onCreate = { Log.i("HelloScreen","onCreate****$number}")},
        onPause = { Log.i("HelloScreen","onPause****$number")},
        onResume = { Log.i("HelloScreen","onResume****$number")},
    )
}


@Composable
fun SnackbarSample() {
    val snackbarHostState = remember { SnackbarHostState() }
    var text by remember { mutableStateOf("") }
    var descrption by remember { mutableStateOf("") }

    LaunchedEffectWrapper1(snackbarHostState, text) { descrption = it }

    // .. code for handling the change of the text state
    Scaffold(
//     attach snackbar host state to the scaffold
        scaffoldState = rememberScaffoldState(snackbarHostState = snackbarHostState),
        content = {
            Column(
                content = {
                    OutlinedTextField(
                        value = text,
                        onValueChange = {
                            text = it
                        },
                        label = { Text("Input") }
                    )
                    Text(descrption)
                }
            )
        }
    )
}

@Composable
fun LaunchedEffectWrapper1(state: SnackbarHostState, text: String, onResult: (String) -> Unit) {

    Text("LaunchedEffectWrapper=1 $text")
    Log.i("LaunchedEffectWrapper=1","******$text")

    val mostRecentText by rememberUpdatedState(text)
    LaunchedEffect(true) {

        Log.i("LaunchedEffectWrapper=2","******$mostRecentText")

        val snackbarResult = state.showSnackbar(
            message = "Are you happy with your input?",
            actionLabel = "Yes",
            duration = SnackbarDuration.Indefinite,
        )
        Log.i("LaunchedEffectWrapper=3","@@@@@$mostRecentText")

        // Do something with text parameter
        when (snackbarResult) {
            SnackbarResult.ActionPerformed -> {
                onResult("final text:${mostRecentText.toUpperCase(Locale.current)}")
            }
            else -> {}
        }
    }
}

@Composable
fun LandingScreen(onTimeout: () -> Unit) {

    // This will always refer to the latest onTimeout function that
    // LandingScreen was recomposed with
    val currentOnTimeout by rememberUpdatedState(onTimeout)

    // Create an effect that matches the lifecycle of LandingScreen.
    // If LandingScreen recomposes, the delay shouldn't start again.
    LaunchedEffect(true) {
        delay(SplashWaitTimeMillis)
        currentOnTimeout()
    }

    Text(text = "Landing*****")
}
